eMMC烧录镜像分区信息剖析

您所在的位置:网站首页 emmc 物理分区 eMMC烧录镜像分区信息剖析

eMMC烧录镜像分区信息剖析

2024-01-17 14:25| 来源: 网络整理| 查看: 265

eMMC和一般硬盘类似,分区信息位于 mmcblk0 的 0 扇区,内核不负责分区的创建,仅仅是读0扇区MBR及分区表即来获得分区信息。 这里讨论的是非GPT的分区问题 eMMC的镜像生成需要用到genimage工具,其需要改配置文件 具体可查阅官方 https://github.com/pengutronix/genimage

比如 genimage --rootpath "genimage/root" --tmppath "genimage/tmp" --inputpath "genimage/input" --outputpath "genimage/image" --config "genimage/gen.cfg" 它会根据gen.cfg中设置的分区信息来自动生成各分区镜像及总镜像

通过genimage生成了eMMC的镜像,再烧录到eMMC后,启动板子后却发现分区不对,分了8个区(包含一个扩展分区信息)加载后发现最后一个15G的分区识别不出来, 一开始感觉是是哪里出了BUG,导致不支持扩展分区上的逻辑分区大于3个,后面发现这个方向不对,因为用fdisk去看烧录的镜像,可以正确看到所有的分区都是在的 /sbin/fdisk -l ./sdcard.img Disk ./sdcard.img:286 MiB,299895296 字节,585733 个扇区 单元:扇区 / 1 * 512 = 512 字节 扇区大小(逻辑/物理):512 字节 / 512 字节 I/O 大小(最小/最佳):512 字节 / 512 字节 磁盘标签类型:dos 磁盘标识符:0x00000000

设备          启动   起点     末尾     扇区  大小 Id 类型 ./sdcard.img1 *         1    12288    12288    6M  c W95 FAT32 (LBA) ./sdcard.img2       12289   217088   204800  100M  0 空 ./sdcard.img3 *    217089   237568    20480   10M  c W95 FAT32 (LBA) ./sdcard.img4      237569 33554431 33316863 15.9G  f W95 扩展 (LBA) ./sdcard.img5      237570   368641   131072   64M 83 Linux ./sdcard.img6      368643   380930    12288    6M  c W95 FAT32 (LBA) ./sdcard.img7      380932   585731   204800  100M  0 空 ./sdcard.img8      585733 33554431 32968699 15.7G 83 Linux 总共16G的eMMC

可以看到第一行起点是1,代表扇区,0扇区就是MBR (一个扇区512字节) 第四行起点是237569,第五行起点是237570,代表第四行的分区占用了1个扇区,这一行是扩展分区,它接在三个主分区后面, 大小是15.9G 5~8这4个分区都是分在扩展分区里的逻辑分区, 且逻辑分区间会有1个扇区的间隔,不同于主分区无间隔,这1个扇区是逻辑分区的分区表信息

MBR dd if=./sdcard.img of=mmc_mbr.bin bs=512 count=1 MBR可以看到三个主分区及扩展分区,逻辑分区则看不到的  /sbin/fdisk -l ./mmc_mbr.bin 读取扩展分区表失败(偏移=237569): 没有那个文件或目录 Disk ./mmc_mbr.bin:512 B,512 字节,1 个扇区 设备           启动   起点     末尾     扇区  大小 Id 类型 ./mmc_mbr.bin1 *         1    12288    12288    6M  c W95 FAT32 (LBA) ./mmc_mbr.bin2       12289   217088   204800  100M  0 空 ./mmc_mbr.bin3 *    217089   237568    20480   10M  c W95 FAT32 (LBA) ./mmc_mbr.bin4      237569 33554431 33316863 15.9G  f W95 扩展 (LBA)

扩展分区 每次能看到2个分区的信息 逻辑分区1,2 dd if=./sdcard.img of=partition.bin bs=512 count=1 skip=237569 /sbin/fdisk -l partition.bin 读取扩展分区表失败(偏移=131073): 没有那个文件或目录 设备           启动   起点   末尾   扇区 大小 Id 类型 partition.bin1           1 131072 131072  64M 83 Linux partition.bin2      131073 143361  12289   6M  f W95 扩展 (LBA)

逻辑分区2,3 dd if=./sdcard.img of=partition2.bin bs=512 count=1 skip=368642 /sbin/fdisk -l partition2.bin 读取扩展分区表失败(偏移=143362): 没有那个文件或目录 设备            启动   起点   末尾   扇区  大小 Id 类型 partition2.bin1           1  12288  12288    6M  c W95 FAT32 (LBA) partition2.bin2      143362 348162 204801  100M  f W95 扩展 (LBA)

逻辑分区3, 4 dd if=./sdcard.img of=partition3.bin bs=512 count=1 skip=380931 /sbin/fdisk -l partition3.bin 读取扩展分区表失败(偏移=348163): 没有那个文件或目录 Disk partition3.bin:512 B,512 字节,1 个扇区 设备            启动   起点     末尾     扇区  大小 Id 类型 partition3.bin1           1   204800   204800  100M  0 空 partition3.bin2      348163 33316862 32968700 15.7G  f W95 扩展 (LBA)

烧录后,在板子上查看分区表信息,如下最后一个分区活生生被吃了,只有1到7,少了8 / # cat /proc/partitions major minor  #blocks  name

   1        0       8192 ram0    1        1       8192 ram1   31        0        512 mtdblock0   31        1        256 mtdblock1   31        2         64 mtdblock2   31        3        512 mtdblock3   31        4        640 mtdblock4   31        5         64 mtdblock5  179        0   15267840 mmcblk0  179        1       6144 mmcblk0p1  179        2     102400 mmcblk0p2  179        3      10240 mmcblk0p3  179        4          1 mmcblk0p4  179        5      65536 mmcblk0p5  179        6       6144 mmcblk0p6  179        7     102400 mmcblk0p7  179       24       4096 mmcblk0boot1  179       12       4096 mmcblk0boot0

/proc/partitions这个是由内核生成的,可以定位到是内核出了问题,只能从源码上着手分析了 eMMC kernel加载过程 mmc_blk_probe->block.c     mmc_add_disk->         add_disk->genhd.c             register_disk->                 blkdev_get->block_dev.c                     __blkdev_get->                         rescan_partitions->partition-generic.c                             check_partition                             add_partition // 这里添加分区信息

//add_partition是由rescan_partition调用的 //block/partition-generic.c int rescan_partitions(struct gendisk *disk, struct block_device *bdev) {     /* add partitions */     for (p = 1; p < state->limit; p++) { // 注意这里state->limit限制了分区数         part = add_partition(disk, p, from, size,                      state->parts[p].flags,                      &state->parts[p].info);     } } // state->limit分区数限制是从哪里来的呢,是从下面这个disk_max_parts来的 static inline int disk_max_parts(struct gendisk *disk) {     if (disk->flags & GENHD_FL_EXT_DEVT)         return DISK_MAX_PARTS;     return disk->minors; // 到这里就变成由minors限定了 } // 这里会把disk_max_parts返回的值赋值给state->limit //block/partitions/check.c static struct parsed_partitions *allocate_partitions(struct gendisk *hd) {     struct parsed_partitions *state;     int nr;     state = kzalloc(sizeof(*state), GFP_KERNEL);     if (!state)         return NULL;     nr = disk_max_parts(hd); // 获取最大分区数     state->parts = vzalloc(nr * sizeof(state->parts[0]));     if (!state->parts) {         kfree(state);         return NULL;     }     state->limit = nr; // 这里对数量做了限制     return state; } // limit由minors来的,那么minors又是从哪里赋值来的呢,看下面这个函数 //drivers/mmc/card/block.c // 这里predev_minor从CONFIG_MMC_BLOCK_MINORS赋值来的,看到有CONFIG_XX就可以猜测是内核的配置中设置的 // 所以如果eMMC镜像写入后,kernel再加载出来分区数少了,很可能是这个CONFIG_MMC_BLOCK_MINORS的值设置小了 // 原因大致是定位到了,接下来是为了验证这个猜想, 看代码 static int perdev_minors = CONFIG_MMC_BLOCK_MINORS; static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,                           struct device *parent,                           sector_t size,                           bool default_ro,                           const char *subname,                           int area_type) {     md->disk = alloc_disk(perdev_minors); // 在这里由perdev_minors赋值来的, alloc_disk的函数名就叫minors } // 这里看函数原型 //block/genhd.c struct gendisk *alloc_disk(int minors) {     return alloc_disk_node(minors, NUMA_NO_NODE); } EXPORT_SYMBOL(alloc_disk); struct gendisk *alloc_disk_node(int minors, int node_id) {             disk->minors = minors; // 这里就是minors的真正赋值的地方 }

修改kernel config中的 CONFIG_MMC_BLOCK_MINORS 为9后就正常了(只要大于8就行), 原始的配置就是8, 所以就少了一个分区 / # cat /proc/partitions major minor  #blocks  name

   1        0       8192 ram0    1        1       8192 ram1   31        0        512 mtdblock0   31        1        256 mtdblock1   31        2         64 mtdblock2   31        3        512 mtdblock3   31        4        640 mtdblock4   31        5         64 mtdblock5  179        0   15267840 mmcblk0  179        1       6144 mmcblk0p1  179        2     102400 mmcblk0p2  179        3      10240 mmcblk0p3  179        4          1 mmcblk0p4  179        5      65536 mmcblk0p5  179        6       6144 mmcblk0p6  179        7     102400 mmcblk0p7  179        8   14974973 mmcblk0p8  179       24       4096 mmcblk0boot1  179       12       4096 mmcblk0boot0  正常

作者:帅得不敢出门



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3